<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html> <head>
<title>&alpha;Rename Tests</title>
<script src="../../src/util/sets.js"></script>
<script src="../../src/util/freevars.js"></script>
<script src="../../src/util/alpharename.js"></script>
<script src="../../src/util/render.js"></script>
<script src="../../site/esparser/bundle.js"></script>
</head>

<body>

<style>
.running { background-color: yellow }
.pass { background-color: #afa }
.fail { background-color: #faa }
td { font-family: monospace; white-space: pre }
</style>

<table id=tests>
  <tr><th>Code<th>Post &alpha;-rename<th>Free vars</tr>
  <tr><td>0<td>0</tr>
  <tr><th colspan=4>Undefined names not renamed.</tr>
  <tr><td>i<td>i</tr>
  <tr><td>var i = 2; alert(i)<td>var $0=2;alert($0)</tr>
  <tr><th colspan=4>Masked identifiers get different names</tr>
  <tr><td>var i = 2; (function (i) { return i * i; })(i);</td>
      <td>var $0=2;(function ($1){return $1*$1})($0)</tr>
  <tr><th colspan=4>Same name used on both sides of a function</tr>
  <tr><td>function fib(i) { if (i &lt; 2) { return i; } return fib(i - 2) + fib(i - 1); }</td>
      <td>function $0($1){if ($1&lt;2){return $1}return ($0($1-2))+($0($1-1))}</tr>
  <tr><td>var f = function () {}; if (x) { function f() { alert('hi'); } f(); }</td>
      <td>var $0=function (){};if (x){function $1(){alert("hi")}$1()}</tr>
  <tr><th colspan=4>eval operator can't be renamed</tr>
  <tr><td>function ex(x, y) { eval(x); }</td>
      <td>throws Error: alpha renaming breaks eval operator</tr>
  <tr><th colspan=4>but eval function can be renamed</tr>
  <tr><td>function f(x, y, eval) { (0, eval)(x); }</td>
      <td>function $0($2,$3,$1){((0,$1))($2)}</tr>
  <tr><th colspan=4>arguments is special sometimes</tr>
  <tr><td>var arguments = foo; alert(arguments);</td>
      <td>var $0=foo;alert($0)</td></tr>
  <tr><td>function f(arguments) { function g() { return arguments; } return g(arguments); }</td>
      <td>function $0($1){function $2(){return arguments}return $2($1)}</td></tr>
  <tr><th colspan=4>labels and names are disjoint namespaces</tr>
  <tr><td>foo: for (var foo = 1; foo &lt; 10; ++foo) {
  if (foo & 1) continue foo;
  alert(foo);
}</td>
      <td>$1:for (var $0=1;$0&lt;10;++$0){if ($0&1)continue $1;alert($0)}</td></tr>
  <tr><td>foo: for (;;) { foo: while (1) { break foo } break foo }</td>
      <td>$0:for (;;){$1:while (1){break $1}break $0}</tr>
  <tr><td>break foo<td>break foo</tr>
  <tr><td>for (;;){break}<td>for (;;){break}</tr>
  <tr><th colspan=4>exception scopes</tr>
  <tr><td>var e = 1;try { alert(e); } catch (e) { throw e; } finally { print(e); }</td>
      <td>var $0=1;try {alert($0)} catch ($1){throw $1} finally {print($0)}</tr>
  <tr><td>var e = 1;try { alert(e); } catch (e) { throw e; }</td>
      <td>var $0=1;try {alert($0)} catch ($1){throw $1}</tr>
  <tr><th colspan=4>with bad</tr>
  <tr><td>with (o) { k = 1; }<td>throws Error: Cannot alpha rename with statements</tr>
  <tr><td>try { e = foo(); } catch (e) { var e = bar(); } return e;</td>
      <td>throws Error: Split initialization of "e"</td>
  <tr><th colspan=4>Property names not rewritten</tr>
  <tr><td>var a, b, c, d; a.b = { d: c, b: a }; c['d'] = a.b(c)</td>
      <td>var $0,$1,$2,$3;$0["b"]={"d":$2,"b":$0};$2["d"]=($0["b"]($2))</tr>
</table>

<script>(function () {
  if (!Date.now) { Date.now = function () { return +(new Date); }; }

  var testsCont = document.getElementById('tests');
  var tests = testsCont.getElementsByTagName('tr');
  var group = function () {};
  var groupEnd = function () {};
  var log = function () {};
  if (typeof console !== 'undefined' && console.group) {
    group = function (name) { console.group(name); };
    groupEnd = function () { console.groupEnd(); };
    log = function (var_args) { console.log.apply(console, arguments); };
  }
  function innerText(el) {
    return el.innerText || el.firstChild.nodeValue;
  }
  function check(cell, actual) {
    var expected = innerText(cell);
    if (actual === expected) {
      cell.className = 'pass';
      return true;
    } else {
      cell.className = 'fail';
      cell.appendChild(document.createTextNode(' ; was\n' + actual));
      return false;
    }
  }
  function makeNamer() {
    var i = 0;
    return function () {
      return '$' + i++;
    };
  }
  var i = 0, n = tests.length;
  function doTest() {
    if (i == n) { return; }
    setTimeout(doTest, 100);
    var test = tests[i++];

    var cells = test.getElementsByTagName('td');
    if (!cells.length) { return; }  // a header row
    test.className = 'running';
    var code = innerText(cells[0]);
    group(code);
    try {
      var t0 = Date.now();
      var ast = ES5Parser.matchAll(code, 'Program', [], function () {});
      var t1 = Date.now();
      var passed = true;
      var freeIdents = '';
      if (ast) {
        var actual;
        try {
          var renamed = alphaRename(ast, makeNamer());
          freeIdents = '' + set_union(free_names(renamed), free_labels(renamed));
          actual = renderEcmascript(renamed);
        } catch (e) {
          actual = 'throws ' + e;
        }
        passed &= check(cells[1], actual);
      } else {
        passed = false;
      }
      var t2 = Date.now();
      test.className = passed ? 'pass' : 'fail';
      var tail = cells[1].nextSibling;
      var th = document.createElement('th');
      th.appendChild(document.createTextNode(freeIdents));
      test.insertBefore(th, tail);

      var timing = 'Of ' + (t2 - t0) + 'ms, parse took '
          + ((t1 - t0) * 100 / (t2 - t0)).toFixed(1) + '%';
      th = document.createElement('th');
      th.appendChild(document.createTextNode(timing));
      test.insertBefore(th, tail);
   } finally {
      groupEnd();
    }
  }
  doTest();
})()</script>

<hr>
<address></address>
<!-- hhmts start --> Last modified: Fri Jan 15 13:12:06 PST 2010 <!-- hhmts end -->
</body> </html>
